/*
* Copyright (c) 2006 by Kirill Kolodyazhniy.
* See the file "license.terms" for information on usage and redistribution.
*/

#ifndef M_THREAD_H
#define M_THREAD_H

#include "threadimpl.h"

#include "atomic.h"
#include "synchronize.h"
#include "event.h"
#include "mutex.h"
#include "refptr.h"
#include "weakptr.h"
#include "signal.h"

namespace Engine
{
	template<class TT,class PP>
	class Thread;

	/**
	*   Class describe thread state functionality.
	*   @param T class that implement threads functionality.
	*   @param P type of parameter passed to T's constructor.
	*   @param Th os specific thread implementation.
	*   @param Ev os specific event synchronization implementation.
	*/
	template<class T,class P = int>
	class ThreadState
	{
	public:
		template<class TT,class PP>
		friend class Thread;

		/**
		*   Thread states.
		*/
		enum {  UNINITIALIZED, INITIALIZED,	WORKING, SLEEPING, DONE, RESUMED };

		/**
		*   Constructor, init events.
		*/
		ThreadState();

		/**
		*   Destructor , destroy events.
		*/
		~ThreadState();

		/**
		*   Reset events and thread state.
		*/
		void Reset();

	private:
		/**
		*   Clear members for constructor and reset.
		*/
		void Clear();

		/**
		*   Private copy constructor.
		*/
		ThreadState( const ThreadState& copyMe );

		/**
		*   Private assignment operator.
		*/
		ThreadState& operator=( const ThreadState& rhs );

		/**
		*   Closing thread handle.
		*   Closing handle twice is an error.
		*/
		void CloseThreadHandle();

		ThreadImpl  m_Thread;      ///< thread object.
		Event       m_RunEvent;  ///< Event for starting thread.
		Event       m_WorkEvent; ///< Event for thread loop.


		// Controls access to following data.
		volatile long m_dwCycleTime;    ///< loop interval.
		volatile long m_bStopThread;    ///< indicate that thread is stoped.
		volatile long m_eState;         ///< current thread state.


		Thread<T,P>* m_pObject; ///< pointer to thread object.
		P            m_param;   ///< parameter that will be passed to threads implementation constructor.
	};


	/**
	*   Class represent thread.
	*   @param T class that implement threads functionality.
	*   @param P type of parameter passed to T's constructor.
	*   @param Th os specific thread implementation.
	*   @param Ev os specific event synchronization implementation.
	*/
	template<class T,class P = int>
	class Thread : public ObjectLevelLockable<Mutex>
	{
	public:
/*
		static void Constraints()
		{
			//concept checking
			sizeof(static_cast<T>(T(static_cast<P>(P()))));
			sizeof(static_cast<bool (T::*)(unsigned long*)>(&T::Task));
		}
*/
		/**
		*   Constructor.
		*   @param dwMilliSecs loop interval.
		*   @param dwStackSize size of stack.
		*/
		Thread(P param = P(),unsigned long dwMilliSecs = 0, unsigned long dwStackSize = 0);

		/**
		*   Destructor.
		*   Stop thread.
		*/
		virtual ~Thread();


		/**
		*   Start thread executing.
		*/
		void Run()const;

		/**
		*   Safely thread terminating.
		*/
		void RequestStop()const;

		/**
		*   Return true if thread stopped.
		*/
		bool IsStopping() const;

		/**
		*   Wakeup thread if he sleeping.
		*/
		void DoWork()const;

		/**
		*   Return loop interval.
		*/
		unsigned long GetCycleTime() const;

		/**
		*   Set loop interval.
		*   @param dwCycleTime interval time.
		*/
		void SetCycleTime( unsigned long dwCycleTime );

		/**
		*   Get thread exit code.
		*/
		unsigned long GetExitCode()const;

		/**
		*   Set thread Priority.
		*/
		void SetPriority( THREAD_PRIORITY priority );

		/**
		*   Suspends caller until DoneEvent is signaled.
		*/
		void WaitUntilDone()const;

		/**
		*   Return thread state.See @see ThreadState for return values.
		*/
		int GetThreadState() const;


		/**
		*   Return weak reference to running object.
		*/
		WeakPtr<T> GetThreadObject(){return m_thObj;}

		/**
		*   Signal emits before thread start waiting work event.
		*/
		Signal<Thread<T,P>* > WaitWorkSignal;

	protected:


		/**
		*   Thread function.
		*/
		static unsigned long ThreadImpl( void* lpParam );


	private:

		/**
		*   Private copy constructor.
		*/
		Thread( const Thread& copyMe );

		/**
		*   Private assignment operator.
		*/
		Thread& operator=( const Thread& rhs );

		mutable ThreadState<T,P> m_td; ///< Thread state object.

		WeakPtr<T> m_thObj;
	};
}
#include "thread.hpp"
#endif
